package com.momoauth.common.core.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * 敏感词过滤工具类
 */
public class SensitiveWord {

    private static String fileName = "censorWords.txt";
    private StringBuilder replaceAll;
    private String replceStr = "*";
    private int replceSize = 500;
    private List<String> arrayList;
    public Set<String> sensitiveWordSet; //包含的敏感词列表，过滤掉重复项
    public List<String> sensitiveWordList; //包含的敏感词列表，包括重复项，统计次数

    /**
     * 文件要求路径在src或resource下，默认文件名为censorWords.txt
     * @param fileName 词库文件名(含后缀)
     */
    public SensitiveWord(String fileName){
        this.fileName = fileName;
    }

    /**
     * @param replceStr 敏感词被转换的字符
     * @param replceSize 初始转义容量
     */
    public SensitiveWord(String replceStr, int replceSize) {
        this.replceStr = fileName;
        this.replceSize = replceSize;
    }

    public SensitiveWord() {}

    /**
     * @param str 将要被过滤信息
     * @return 过滤后的信息
     */
    public String filterInfo(String str){
        sensitiveWordSet = new HashSet<String>();
        sensitiveWordList = new ArrayList<>();
        StringBuilder buffer = new StringBuilder(str);
        HashMap<Integer, Integer> hash = new HashMap<Integer, Integer>(arrayList.size());
        String temp;
        for (int x = 0; x < arrayList.size(); x++)
        {
            temp = arrayList.get(x);
            int findIndexSize = 0;
            for (int start = -1;(start=buffer.indexOf(temp,findIndexSize)) > -1;)
            {
                findIndexSize = start+temp.length();//从已找到的后面开始找
                Integer mapStart = hash.get(start);//起始位置
                if (mapStart == null || findIndexSize > mapStart) //满足1个，即可更新map
                {
                    hash.put(start, findIndexSize);
                }
            }
        }
        Collection<Integer> values = hash.keySet();
        for (Integer startIndex : values)
        {
            Integer endIndex = hash.get(startIndex);
            //获取敏感词，并加入列表，用来统计数量
            String sensitive = buffer.substring(startIndex, endIndex);
            if (!sensitive.contains("*")) { //添加敏感词到集合
                sensitiveWordSet.add(sensitive);
                sensitiveWordList.add(sensitive);
            }
            buffer.replace(startIndex, endIndex, replaceAll.substring(0, endIndex-startIndex));
        }
        hash.clear();
        return buffer.toString();
    }

    /**
     *   初始化敏感词库
     */
    public void InitializationWork() {
        replaceAll = new StringBuilder(replceSize);
        for (int x=0;x < replceSize;x++)
        {
            replaceAll.append(replceStr);
        }
        //加载词库
        arrayList = new ArrayList<String>();
        InputStreamReader read = null;
        BufferedReader bufferedReader = null;
        try {
            String encoding = "UTF-8";
            read = new InputStreamReader(SensitiveWord.class.getClassLoader().getResourceAsStream(fileName), encoding);
            bufferedReader = new BufferedReader(read);
            for (String txt = null;(txt = bufferedReader.readLine()) != null;) {
                if (!arrayList.contains(txt))
                    arrayList.add(txt);
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != bufferedReader)
                    bufferedReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (null != read)
                    read.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 过滤字符串
     * @param str
     * @return
     */
    public static String filterStr(String str) {
        SensitiveWord sw = new SensitiveWord(fileName);
        try {
            sw.InitializationWork();
            str = sw.filterInfo(str);
        } catch (Exception ignored) {};
        return str;
    }
}
